using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints;
using FarseerPhysics.Factories;
using System.Xml;
using System.Xml.Serialization;
using System.Text;
using System.IO;

namespace MountainORocks
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        public SpriteFont myFont, myFont2;
        public Texture2D gameOverTexture,levelUpTexture,levelDoneTexture,droperTexture,muteTexture,menuBackTexture,shatterTexture,charTexture, builderTexture,stockTexture,storeIconTexture, playTexture,shopTexture, menuBTexture, backgroundTexture,mainTexture, glassCirTexture, crystalSTexture, arrowTexture, woodCirTexture, woodSquTexture, rockCirTexture, rockSquTexture, exitTexture;
        public Texture2D noRockTexture, powerTexture, dimondTexture, glassRecTexture;
        public int playerW = 18;
        public int playerH = 32;
        public enum GameState { play, builder, menu, win, lose, done, howto, playMenu, shopMenu };
        public enum Info { yes, no };
        public Info info = Info.no;
        public GameState gameState = GameState.menu;
        WorldBuilder gameBuilder;
        public World world;
        public int level = 1;
        public Body border,floor;
        public Body charBody;
        public Body exitDoor;
        Song soundEffect;
        public int playerMoney = 9999;
        Vector2 off= new Vector2(9,80);
        Color play = Color.Black, build = Color.Black, how = Color.Black;
        Player myPlayer;
        public int maxLevel = 1;
        // screen size
        public int HEIGHT = 600;
        public int WIDTH = 800;
        public float delay;
        double delayBeforeExit = 0;
        dropStuff myDroper;
        private bool open = false;
        public List<GameShape> rocks = new List<GameShape>();
        public List<dropStuff> dropList = new List<dropStuff>();
        double eliminateTimeConst = 5.0;
        double eliminateTime = 0;
        public MouseState currentMouseState;
        bool doBuildWorld = true;
        bool isMute = false;
        Rectangle createGameRect, playGameRect, arrowRight , arrowLeft, goShop;
        Rectangle inforec;
        int playMenuPlace = 0;
        string[] ans;
        public int levelCount,live;
        int menuStartX, menuStartY;
        const int rawCount = 5;
        const int colCount = 5;
        const int paddingX = 2;
        const int paddingY = 2;
        MouseState mState;
        public double timeBeforeChange = 0.2;
        public double opentime = 0.2;
        public double timeBeforeChangeConst = 0.2;
        double waitbeforemute = 0.1;
        int j = 0;
        public double bonusPower = 1;
        public int rocksPower = 0;
        public int rocksLevel = 0;
        private int prize = 5;
        private const float bonusTimeConst = 0.3f;
        private const int bonusPowerConst = 500;
        private bool reset = false;
        private double timeBonusing;
        private Boolean superPower, building=false;
        private Rectangle muteButton;
       
        bool playing = false;
        private bool loader = false;
        private bool refresh = false;
        private bool dirty = false;
        
        
        Shop myShop;
        Color newColor = Color.White;
        PowerController powerController; // the power meter

        Lightning lightning;

        struct gameInMenu
        {
            public int num;
            public Rectangle place;

        };
        List<gameInMenu> menuList = new List<gameInMenu>();

        GameShape currSelectedShape;

        // everything that is needed for particles
        ParticleManager pManager;
        Texture2D smokeText;
        private bool choose=false;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
         
        public bool Building {get{return building;}}
        public void setBuilding() { building = false; }
        public bool Refresh { get { return refresh; } }
        public void setRefresh()  {  refresh = false ; }
        public int Level { get { return level; } }
        public bool getDirty { get { return dirty; } }
        public void setDirty() { dirty = false; }

        public List<GameShape> getRocks { get { return rocks; } }
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            if (Directory.Exists(Content.RootDirectory + @"\Levels") == false)
            {
                Directory.CreateDirectory(Content.RootDirectory + @"\Levels");
            }
            ans = Directory.GetFiles(Content.RootDirectory + @"\Levels");
            levelCount = ans.Length;

            // no shape is currently selected
            menuStartX = 250;
            menuStartY = 150;
            // set screen size
            graphics.PreferredBackBufferHeight = HEIGHT;
            graphics.PreferredBackBufferWidth = WIDTH;
            graphics.IsFullScreen = false;
            graphics.ApplyChanges();
            HEIGHT = graphics.PreferredBackBufferHeight;
            WIDTH = graphics.PreferredBackBufferWidth;

            this.IsMouseVisible = true;
            // setup world
            createGameRect = new Rectangle(WIDTH / 2 - 100, HEIGHT / 2 - 50, 200, 50);
            playGameRect = new Rectangle(WIDTH / 2 - 100, HEIGHT / 2 - 150, 200, 50);
            arrowLeft = new Rectangle(WIDTH / 2 - 70, HEIGHT - 118, 64, 32);
            arrowRight = new Rectangle(WIDTH / 2 + 30, HEIGHT - 118, 64, 32);
            goShop = new Rectangle(WIDTH/2 - 350,HEIGHT-200,128,128);
            inforec = new Rectangle(WIDTH / 2 - 100, HEIGHT / 2 + 50, 200, 50);
            delay = 5;
            live = 2;
            myPlayer = new Player(this);
            gameBuilder = new WorldBuilder(WIDTH, HEIGHT, playerW, playerH, this, myPlayer);
            muteButton = new Rectangle(WIDTH - 128, HEIGHT - 80, 64, 64);
            
            myShop = new Shop(this);

            
            
            // power remover
            timeBonusing = bonusTimeConst;

            base.Initialize();
        }

        public void buildWorld()
        {
            myPlayer.setNotDead();
            opentime = 0.2;
            ans = Directory.GetFiles(Content.RootDirectory + @"\Levels");
            levelCount = ans.Length;
            j = 0;
            open = false;
            world = new World(new Vector2(0f, 1000f));
            delay = 5;
            // setup world border

            Vertices borders = new Vertices(4);
            borders.Add(new Vector2(0 + 0, 0 + 0));
            borders.Add(new Vector2(WIDTH - 0, 0 + 0));
            borders.Add(new Vector2(WIDTH - 0, HEIGHT - 0));
            borders.Add(new Vector2(0, HEIGHT));

            border = BodyFactory.CreateLoopShape(world, borders);
            // border.Friction = 0.5f;
            border.CollisionCategories = Category.All;
            border.CollidesWith = Category.All;
            border.Friction = 1.8f;
            border.UserData = (object)ShapeM.Stone;
            /*floor = BodyFactory.CreateRectangle(world, WIDTH, 1, 1);
            floor.Position = new Vector2(0, HEIGHT);
            floor.Friction = 1.8f;
            floor.CollisionCategories = Category.All;
            floor.CollidesWith = Category.All;
            */
            world.Gravity = new Vector2(0, 120f);
            exitDoor = new Body(world, PolygonTools.CreateRectangle(32 / 2, 32 / 2, new Vector2(32 / 2, 32 / 2), 0.0f));
            exitDoor.BodyType = BodyType.Static;
            exitDoor.CreateFixture(new PolygonShape(PolygonTools.CreateRectangle(32 / 2, 32 / 2, new Vector2(32 / 2, 32 / 2), 0.0f), 1));
            exitDoor.Friction = 1.0f;
            exitDoor.Mass = 50000f;
            exitDoor.Position = new Vector2(WIDTH - 60, HEIGHT - playerH);
            exitDoor.FixedRotation = true;
            exitDoor.UserData = (object)ShapeM.Stone;
            // setup player
            // setup char


            Vertices vert = PolygonTools.CreateRectangle(playerW / 2, playerH / 2, new Vector2(playerW / 2, playerH / 2), 0.0f);
            charBody = new Body(world, vert);
            charBody.BodyType = BodyType.Dynamic;
            charBody.UserData = (object)ShapeM.Stone;
            charBody.CreateFixture(new PolygonShape(vert, 1));
            charBody.Position = new Vector2(WIDTH / 2 + 60, HEIGHT - playerH);
            charBody.Friction = 1.4f;
            charBody.Mass = 300f;
            charBody.CollisionCategories = Category.All;
            
            charBody.FixedRotation = true;
            charBody.LinearDamping = 0.2f;
            // setup the power meter
            powerController = new PowerController(graphics.GraphicsDevice);

            

            //charBody.FixedRotation = false;

            charBody.OnCollision += new OnCollisionEventHandler(myPlayer.charBody_OnCollision);
            //rocks.Add(new GameShape(world, ShapeType.Rect, new Rectangle(20, 20, 32, 32), Color.Blue,true));
            rocks.Clear();
            dropList.Clear();
            loadLevels();
            myDroper = new dropStuff(ShapeType.Circle, ShapeM.Glass, new Vector2(64, 64), false, 15.0, level * 2, this);
            doBuildWorld = false;


        }


        public void buildWorldEmpty()
        {
            myPlayer.setNotDead();
            opentime = 0.2;
            ans = Directory.GetFiles(Content.RootDirectory + @"\Levels");
            levelCount = ans.Length;
            j = 0;
            open = false;
            world = new World(new Vector2(0f, 1000f));
            delay = 5;
            // setup world border

            Vertices borders = new Vertices(4);
            borders.Add(new Vector2(0 + 0, 0 + 0));
            borders.Add(new Vector2(WIDTH - 0, 0 + 0));
            borders.Add(new Vector2(WIDTH - 0, HEIGHT - 0));
            borders.Add(new Vector2(0, HEIGHT));

            border = BodyFactory.CreateLoopShape(world, borders);
            // border.Friction = 0.5f;
            border.CollisionCategories = Category.All;
            border.CollidesWith = Category.All;
            border.Friction = 1.8f;
            border.UserData = (object)ShapeM.Stone;
            /*floor = BodyFactory.CreateRectangle(world, WIDTH, 1, 1);
            floor.Position = new Vector2(0, HEIGHT);
            floor.Friction = 1.8f;
            floor.CollisionCategories = Category.All;
            floor.CollidesWith = Category.All;
            */
            world.Gravity = new Vector2(0, 120f);
            exitDoor = new Body(world, PolygonTools.CreateRectangle(32 / 2, 32 / 2, new Vector2(32 / 2, 32 / 2), 0.0f));
            exitDoor.BodyType = BodyType.Static;
            exitDoor.CreateFixture(new PolygonShape(PolygonTools.CreateRectangle(32 / 2, 32 / 2, new Vector2(32 / 2, 32 / 2), 0.0f), 1));
            exitDoor.Friction = 1.0f;
            exitDoor.Mass = 50000f;
            exitDoor.Position = new Vector2(WIDTH - 60, HEIGHT - playerH);
            exitDoor.FixedRotation = true;
            
            // setup player
            // setup char
            exitDoor.UserData = (object)ShapeM.Stone;
            Vertices vert = PolygonTools.CreateRectangle(playerW / 2, playerH / 2, new Vector2(playerW / 2, playerH / 2), 0.0f);
            charBody = new Body(world, vert);
            charBody.BodyType = BodyType.Dynamic;
            charBody.UserData = (object)ShapeM.Stone;
            charBody.CreateFixture(new PolygonShape(vert, 1));
            charBody.Position = new Vector2(WIDTH / 2 + 60, HEIGHT - playerH);
            charBody.Friction = 1.4f;
            charBody.Mass = 300f;
            charBody.CollisionCategories = Category.All;

            charBody.FixedRotation = true;
            charBody.LinearDamping = 0.2f;
            // setup the power meter
            powerController = new PowerController(graphics.GraphicsDevice);
            

            //charBody.FixedRotation = false;

            charBody.OnCollision += new OnCollisionEventHandler(myPlayer.charBody_OnCollision);
            //rocks.Add(new GameShape(world, ShapeType.Rect, new Rectangle(20, 20, 32, 32), Color.Blue,true));
            rocks.Clear();
            
            myDroper = new dropStuff(ShapeType.Circle, ShapeM.Glass, new Vector2(64, 64), false, 15.0, level * 2, this);
            doBuildWorld = false;


        }

        
        
       /* void Coll()
        {

            if ((Math.Abs(exitDoor.Position.X - charBody.Position.X) < 32 + 1) && (Math.Abs(exitDoor.Position.Y - charBody.Position.Y) < 32 + 1))
            {
                if (level < levelCount) { gameState = GameState.win; }
                else { gameState = GameState.done; }
            }
            if ((Math.Abs(exitDoor.Position.X - charBody.Position.X) < 32 + 30) && (Math.Abs(exitDoor.Position.Y - charBody.Position.Y) < 32 + 30))
            {
                open = true;
            }

                

            
        }
        */

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            charTexture = Content.Load<Texture2D>(@"Textures\char2");
            builderTexture = Content.Load<Texture2D>(@"Textures\builder");
            playTexture = Content.Load<Texture2D>(@"Textures\play");
            backgroundTexture = Content.Load<Texture2D>(@"Textures\dorcia_262f");
            arrowTexture = Content.Load<Texture2D>(@"Textures\arrow");
            Player.loadContact(Content.Load<Texture2D>(@"Textures\playerT"), Content.Load<Texture2D>(@"Textures\playerDead"));
            myFont = Content.Load<SpriteFont>(@"Fonts\myFont");
            myFont2 = Content.Load<SpriteFont>(@"Fonts\myFont2");
            woodCirTexture = Content.Load<Texture2D>(@"Textures\woodCir2");
            woodSquTexture = Content.Load<Texture2D>(@"Textures\woodRec");
            rockCirTexture = Content.Load<Texture2D>(@"Textures\rock_circle");
            rockSquTexture = Content.Load<Texture2D>(@"Textures\rock_rec");
            glassCirTexture = Content.Load<Texture2D>(@"Textures\circleGlass");
            crystalSTexture = Content.Load<Texture2D>(@"Textures\crystal");
            shopTexture = Content.Load<Texture2D>(@"Textures\shop");
            exitTexture = Content.Load<Texture2D>(@"Textures\door2");
            mainTexture = Content.Load<Texture2D>(@"Textures\start");
            stockTexture = Content.Load<Texture2D>(@"Textures\stock");
            storeIconTexture = Content.Load<Texture2D>(@"Textures\shop-icon");
            droperTexture = Content.Load<Texture2D>(@"Textures\droper");
            shatterTexture = Content.Load<Texture2D>(@"Textures\gPar");
            menuBackTexture = Content.Load<Texture2D>(@"Textures\menuBack");
            glassRecTexture = Content.Load<Texture2D>(@"Textures\recGlass");
            muteTexture = Content.Load<Texture2D>(@"Textures\mute");
            GameShape.loadTexture(woodSquTexture, woodCirTexture, rockSquTexture, rockCirTexture, glassRecTexture, glassCirTexture, crystalSTexture, this); 
            menuBTexture = Content.Load<Texture2D>(@"Textures\menuB");
            noRockTexture = Content.Load<Texture2D>(@"Textures\noRock");
            powerTexture = Content.Load<Texture2D>(@"Textures\power");
            dimondTexture = Content.Load<Texture2D>(@"Textures\dimond");
            levelUpTexture = Content.Load<Texture2D>(@"Textures\levelUp");
            levelDoneTexture = Content.Load<Texture2D>(@"Textures\gameDone");
            gameOverTexture = Content.Load<Texture2D>(@"Textures\gameOver");
            soundEffect = Content.Load<Song>(@"sound\06_Mindfields_edit");
            // TODO: use this.Content to load your game content here

            // particles
            pManager = new ParticleManager(spriteBatch);
            smokeText = Content.Load<Texture2D>(@"Textures\smoke_particle");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit

            delayBeforeExit -= gameTime.ElapsedGameTime.TotalSeconds;
            waitbeforemute -= gameTime.ElapsedGameTime.TotalSeconds;
            currentMouseState = Mouse.GetState();
           // if (charBody!=null)
           // charBody.Mass = 10;
            KeyboardState keyState = Keyboard.GetState();
            
                switch (gameState)
                {

                    case GameState.shopMenu:
                        {
                            myShop.update(gameTime);
                            if (delayBeforeExit < 0 && Keyboard.GetState().IsKeyDown(Keys.Escape))
                            {
                                gameState = GameState.playMenu;
                                delayBeforeExit = 0.5;
                            }
                            break;
                        }
                    case GameState.menu:
                        {
                            
                            level = 1;
                            live = 2;
                            doBuildWorld = true;
                            mState = Mouse.GetState();
                            if (delayBeforeExit < 0 && Keyboard.GetState().IsKeyDown(Keys.Escape))
                                this.Exit();
                            if (currentMouseState.LeftButton == ButtonState.Pressed)
                            {
                                
                                    ans = Directory.GetFiles(Content.RootDirectory + @"\Levels");
                                    levelCount = ans.Length;
                                   // levelCount = 66; //**** delete
                                    menuList.Clear();
                                    for (int i = 0; i < levelCount; i++)
                                    {
                                        Rectangle tmp = new Rectangle(menuStartX + ((i % 25) % rawCount) * (64 + paddingX), menuStartY + ((i % 25) / rawCount) * (64 + paddingY), 64, 64);
                                        gameInMenu tmp2;
                                        tmp2.num = i + 1;
                                        tmp2.place = tmp;
                                        menuList.Add(tmp2);
                                        
                                    }
                                if (playGameRect.Intersects(new Rectangle(currentMouseState.X, currentMouseState.Y, 2, 2)))
                                {
                                    gameState = GameState.playMenu;
                                    delay = 0.5f;

                                }
                                if (createGameRect.Intersects(new Rectangle(currentMouseState.X, currentMouseState.Y, 2, 2)))
                                {
                                    gameBuilder.newWorld();
                                    gameState = GameState.builder;

                                }
                                if (inforec.Intersects(new Rectangle(currentMouseState.X, currentMouseState.Y, 2, 2)))
                                {
                                    
                                    gameState = GameState.howto;

                                }
                                if (waitbeforemute<0 && muteButton.Intersects(new Rectangle(currentMouseState.X, currentMouseState.Y, 2, 2)))
                                {
                                    waitbeforemute = 0.1;
                                    isMute = !isMute;
                                    if (playing && isMute)
                                    {
                                        playing = false;
                                        MediaPlayer.Stop();
                                    }

                                }
                                

                            

                            }
                            Color tintColor = Color.Cornsilk;
                            tintColor.A = 30;

                            if (playGameRect.Intersects(new Rectangle(currentMouseState.X, currentMouseState.Y, 2, 2)))
                            {
                                play = tintColor;
                            }
                            else { play = Color.Black; }
                            if (createGameRect.Intersects(new Rectangle(currentMouseState.X, currentMouseState.Y, 2, 2)))
                            {
                                build = tintColor;
                            }
                            else { build = Color.Black; }
                            if (inforec.Intersects(new Rectangle(currentMouseState.X, currentMouseState.Y, 2, 2)))
                            {
                                how = tintColor;
                            }
                            else { how = Color.Black; }


                            if (playing == false && isMute==false)
                            {
                                playing = true;
                                MediaPlayer.Play(soundEffect);
                                MediaPlayer.IsRepeating = true;

                            }
                            break;
                        }
                    case GameState.builder:
                        {
                            
                            if (playing == true)
                            {
                                playing = false;
                                MediaPlayer.Stop();
                            }
                            if (info == Info.no)
                            {
                                exitDoor.IgnoreCollisionWith(charBody);
                                building = true;
                                if (doBuildWorld)
                                {
                                    doBuildWorld = false;
                                    buildWorld();
                                }

                                if (currentMouseState.RightButton == ButtonState.Pressed)
                                {

                                    Fixture savedFixture = world.TestPoint(new Vector2(currentMouseState.X, currentMouseState.Y));

                                    if ((savedFixture != null) && (savedFixture.Body != charBody) && (savedFixture.Body != exitDoor))
                                    {

                                        RemoveShapeBuilder(savedFixture.Body, true);

                                    }

                                }
                                if (Keyboard.GetState().IsKeyDown(Keys.L) && (!loader))
                                {

                                    loader = true;
                                    dirty = true;
                                    gameState = GameState.playMenu;

                                }
                                if (Keyboard.GetState().IsKeyUp(Keys.L) && (loader)) { loader = false; }

                                if (Keyboard.GetState().IsKeyDown(Keys.I))
                                {
                                    building = false;
                                    info = Info.yes;
                                }
                                if (delayBeforeExit < 0 && Keyboard.GetState().IsKeyDown(Keys.Escape))
                                {
                                    building = false;
                                    gameState = GameState.menu;
                                    delayBeforeExit = 0.5;
                                }
                                //doBuildWorld = true;

                                gameBuilder.update(gameTime);
                            }
                            else
                            {
                                if (Keyboard.GetState().IsKeyUp(Keys.I))
                                {
                                    building = false;
                                    info = Info.no;

                                }
                            }

                            break;
                        }
                    case GameState.playMenu:
                        {
                            
                            if (goShop.Contains(Mouse.GetState().X, Mouse.GetState().Y))
                            {
                                newColor = Color.Cornsilk;
                                newColor.A = 30;
                            }
                            else
                                newColor = Color.White;

                            delay -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                            if (delayBeforeExit < 0 && Keyboard.GetState().IsKeyDown(Keys.Escape))
                            {
                                gameState = GameState.menu;
                                delayBeforeExit = 0.5;
                            }

                            if ((delay<0) && (Mouse.GetState().LeftButton == ButtonState.Pressed))
                            {
                                delay = 1.0f;
                                if (goShop.Contains(Mouse.GetState().X, Mouse.GetState().Y))
                                {
                                    gameState = GameState.shopMenu;
                                    delayBeforeExit = 0.5;

                                }
                                foreach (gameInMenu levelB in menuList)
                                {
                                    if ((levelB.num >= playMenuPlace*25) && (playMenuPlace*25 + 25>=levelB.num) && (levelB.place.Intersects(new Rectangle(Mouse.GetState().X, Mouse.GetState().Y, 2, 2))))
                                    {
                                        
                                        refresh = true;
                                        if ((maxLevel >= levelB.num)|(building))
                                        {
                                            doBuildWorld = true;
                                            level = levelB.num;
                                            live = 3;
                                            choose = true;
                                            if (building == false)
                                            {
                                                gameState = GameState.play;
                                                
                                                
                                            }
                                            else
                                            {
                                                building = false;
                                                gameState = GameState.builder;
                                            }
                                        }
                                        break;
                                    }

                                }

                                if ((arrowLeft.Intersects(new Rectangle(Mouse.GetState().X, Mouse.GetState().Y, 5, 5))) && (playMenuPlace > 0))
                                {
                                    playMenuPlace--;
                                }

                                if ((arrowRight.Intersects(new Rectangle(Mouse.GetState().X, Mouse.GetState().Y, 5, 5))) && (playMenuPlace*25 + 25 < levelCount))
                                {
                                    playMenuPlace++;
                                }

                                

                            }

                            break;
                        }
                    case GameState.win:
                        {
                            if (delay <= 0)
                            {

                                level++;
                                playerMoney += prize;
                                maxLevel = Math.Max(level, maxLevel);
                                gameState = GameState.play;
                                buildWorld();
                               
                                live = 3;
                                prize = 5;
                                break;
                            }
                            else { break; }
                        }
                    case GameState.lose:
                        {
                            if (delay <= 0)
                            {

                                level = 1;
                                gameState = GameState.menu;
                                // buildWorld();
                                doBuildWorld = true;
                                
                                live = 3;
                                if (playing == true)
                                {
                                    playing = false;
                                    MediaPlayer.Stop();
                                }
                                break;
                            }
                            else { break; }
                        }
                    case GameState.done:
                        {
                            if (delay <= 0)
                            {
                                gameState = GameState.menu;
                                buildWorld();
                                live = 3;
                                if (playing == true)
                                {
                                    playing = false;
                                    MediaPlayer.Stop();
                                }
                                break;
                            }
                            else { break; }
                        }
                    case GameState.play:
                        {
                            if ((keyState.IsKeyDown(Keys.LeftShift)) && (powerController.getPower() > bonusPowerConst))
                            {
                                superPower = true;
                            }
                            else
                            {
                                superPower = false;
                                timeBonusing = bonusTimeConst;
                            }

                            if (superPower) myPlayer.powerMult = 9f;
                            else myPlayer.powerMult = 1f;

                            if (superPower) timeBonusing -= gameTime.ElapsedGameTime.TotalSeconds;

                            if (timeBonusing < 0)
                            {
                                timeBonusing = bonusTimeConst;
                                powerController.RemovePower(bonusPowerConst);
                            }


                            if (delayBeforeExit < 0 && Keyboard.GetState().IsKeyDown(Keys.Escape))
                            {
                                gameState = GameState.menu;
                                delayBeforeExit = 0.5;
                            }
                            if (Keyboard.GetState().IsKeyDown(Keys.I))
                            {
                                info = Info.yes;
                            }
                            if (doBuildWorld)
                                buildWorld();
                            eliminateTime -= gameTime.ElapsedGameTime.TotalSeconds;
                            myDroper.update(gameTime);

                            foreach (dropStuff tmpDrop in dropList)
                            {
                                tmpDrop.update(gameTime);
                            }

                            int i = 0;
                            while (i < rocks.Count)
                            {
                                rocks[i].update(gameTime);
                                if (rocks[i].getRemoveMe())
                                {
                                    RemoveShape(rocks[i].body,false);

                                  
                                }
                                else
                                    i++;

                            }
                     

                            if ((eliminateTime < 100) && (currentMouseState.LeftButton == ButtonState.Pressed))
                            {

                                Fixture savedFixture = world.TestPoint(new Vector2(currentMouseState.X, currentMouseState.Y));
                                
                                if ((savedFixture != null) && (savedFixture.Body != charBody) && (savedFixture.Body != exitDoor))
                                {
                                    
                                    RemoveShape(savedFixture.Body,true);
                                    
                                }



                                eliminateTime = eliminateTimeConst;
                            }

                            if (keyState.IsKeyDown(Keys.R)&&(!reset))
                            {
                                myPlayer.resetDead();
                                buildWorld();
                                if (prize > 0) { prize--; }
                                else { prize = 0; }
                                reset = true;
                            }
                            if (keyState.IsKeyUp(Keys.R) && (reset)) { reset = false; }
                            myPlayer.Update(gameTime);
                           
                            // check what shape is selected 
                            currSelectedShape = null;
                            Fixture getFixture = world.TestPoint(new Vector2(currentMouseState.X, currentMouseState.Y));
                            if (getFixture != null)
                            {
                                foreach (GameShape shape in rocks)
                                {
                                    if ((shape.canDisappear || rocksPower>0) && shape.body == getFixture.Body) currSelectedShape = shape;
                                }
                            }

                           

                            // update power meter for selected shape
                            if (currSelectedShape != null) powerController.setSelected((int)(currSelectedShape.getPower()*bonusPower)); // just default need to change
                            else powerController.setSelected(0);

                            
                            world.Step((float)gameTime.ElapsedGameTime.TotalSeconds);
                            break;
                        }
                    case GameState.howto:
                        {

                            if (delayBeforeExit < 0 && Keyboard.GetState().IsKeyDown(Keys.Escape))
                            {
                                gameState = GameState.menu;
                                delayBeforeExit = 0.5;
                            }
                            break;
                        }
                }


                if (this.lightning != null) this.lightning.Update(gameTime);


                pManager.UpdateParticles((float)gameTime.ElapsedGameTime.TotalSeconds);    

                base.Update(gameTime);


                
            
        }

        public void RemoveShape(Body body, bool wasClicked)
        {
            bool removed = false;

            


            body.Awake = true;
            ShapeM tmpM = ShapeM.Stone;
            foreach (GameShape shape in rocks)
            {
                if (shape.body == body && (shape.canDisappear || rocksPower>0))
                {
                    if ((wasClicked) && (shape.shapMat == ShapeM.Crystal))
                        return;
                    tmpM = shape.shapMat;
                    if ((shape.canDisappear == false) && (wasClicked))
                        rocksPower--;
                    if (shape.shapMat == ShapeM.Crystal)
                    {
                        
                       
                        rocks.Remove(shape);
                        removed = true;
                        break;
                    }
                    if (shape.shapMat == ShapeM.Glass)
                    {
                        if (wasClicked) { powerController.RemovePower((int)(shape.getPower() * bonusPower)); }
                        int rand = dropStuff.generator.Next(2);
                        if (rand==1)
                            rocks.Add(new GameShape(world, ShapeType.Rect, ShapeM.Crystal, new Rectangle((int)shape.body.Position.X, (int)shape.body.Position.Y, 16, 16)));
                        rocks.Remove(shape);
                        removed = true;
                        break;
                    }
                    if (wasClicked && powerController.RemovePower((int)(shape.getPower() * bonusPower)))
                    {// just default need to change
                        rocks.Remove(shape);
                        removed = true;
                    }
                    break;
                }
                
            }

            if (removed)
            {

                // draw lightning
                if (wasClicked)
                {
                    Vector2 start = body.Position;
                    Vector2 end = charBody.Position;

                    this.lightning = new Lightning(start, end, graphics.GraphicsDevice);
                }

                // Remove clicked body
                this.world.RemoveBody(body);


                Random rand = new Random();
                // draw smoke
                
                /* Not used anymore
                Vector2 location = new Vector2((float)rand.Next((int)body.Position.X -25, (int)body.Position.X + 25),
                    (float)rand.Next((int)body.Position.Y - 25, (int)body.Position.Y + 25));
                */

                if (tmpM == ShapeM.Glass)
                {
                    for (int i = 0; i < 2; i++)
                    {
                        // random trajectory
                        Vector2 trajectory = new Vector2((float)rand.Next(-30, 30), (float)rand.Next(-30, 30));

                        // add the smoke particle
                        pManager.AddParticle(new Shatter(body.WorldCenter,
                            trajectory,
                            1.0f, 1.0f, 1.0f, 1.0f, (1 - 1 / body.Mass), (float)rand.NextDouble()));

                    }

                }
                else
                {
                    if (tmpM == ShapeM.Crystal)
                    {
                        for (int i = 0; i < 2; i++)
                        {
                            // random trajectory
                            Vector2 trajectory = new Vector2((float)rand.Next(-30, 30), (float)rand.Next(-30, 30));

                            // add the smoke particle
                            pManager.AddParticle(new Smoke(body.WorldCenter,
                                trajectory,
                                1.0f, 1.0f, 1.0f, 1.0f, 0.2f, (float)rand.NextDouble()));

                        }

                    }
                    else
                    {

                        for (int i = 0; i < 10; i++)
                        {
                            // random trajectory
                            Vector2 trajectory = new Vector2((float)rand.Next(-100, 100), (float)rand.Next(-100, 100));

                            // add the smoke particle
                            pManager.AddParticle(new Smoke(body.WorldCenter,
                                trajectory,
                                1.0f, 1.0f, 1.0f, 1.0f, (1 - 1 / body.Mass), (float)rand.NextDouble()));

                        }
                    }
                }

                // rewake all the world 
                foreach (GameShape shape in rocks)
                {
                    shape.body.Awake = true;
                }
            }

        }

        public void RemoveShapeBuilder(Body body, bool wasClicked)
        {
            bool removed = false;

            body.Awake = true;
            ShapeM tmpM = ShapeM.Stone;
            foreach (GameShape shape in rocks)
            {
                if (shape.body == body)
                {
                    if ((wasClicked) && (shape.shapMat == ShapeM.Crystal))
                        return;
                    tmpM = shape.shapMat;
                    if (shape.shapMat == ShapeM.Crystal)
                    {
                        playerMoney += 10;
                        rocks.Remove(shape);
                        removed = true;
                        break;
                    }
                    if (shape.shapMat == ShapeM.Glass)
                    {
                        int rand = dropStuff.generator.Next(4);
                        if (rand == 1)
                            rocks.Add(new GameShape(world, ShapeType.Rect, ShapeM.Crystal, new Rectangle((int)shape.body.Position.X, (int)shape.body.Position.Y, 16, 16)));
                        rocks.Remove(shape);
                        removed = true;
                        break;
                    }
                    if (wasClicked)
                    {// just default need to change
                        rocks.Remove(shape);
                        removed = true;
                    }
                    break;
                }

            }

            if (removed)
            {
                // Remove clicked body
                this.world.RemoveBody(body);


                // rewake all the world 
                foreach (GameShape shape in rocks)
                {
                    shape.body.Awake = true;
                }
            }

        }
        public void loadLevels()
        {
            LevelData mythingtoload;
            //Content.Load<LevelData>(@"Levels\myfile.xml");

            FileStream file = new FileStream(Content.RootDirectory + @"\Levels\myfile" + level.ToString() + ".xml", FileMode.OpenOrCreate);
            XmlSerializer serialize = new XmlSerializer(typeof(LevelData));
            mythingtoload = (LevelData)serialize.Deserialize(file);
            file.Close();
            
            // clear level
            
            if (mythingtoload != null)
            {
                foreach (ShapeData myData in mythingtoload.level)
                {
                    ShapeType type;
                    if (myData.type == "Circle")
                        type = ShapeType.Circle;
                    else
                        type = ShapeType.Rect;

                    ShapeM typeM=ShapeM.Stone;
                    if (myData.material == "Stone")
                        typeM = ShapeM.Stone;
                    if (myData.material == "Wood")
                        typeM = ShapeM.Wood;
                    if (myData.material == "Glass")
                        typeM = ShapeM.Glass;

                    GameShape tmp = new GameShape(world, type, typeM, new Rectangle(myData.positionX, myData.positionY, myData.width, myData.hight), myData.isStatic);
                    rocks.Add(tmp);
                }

                foreach (ShapeDataDroper myDroper in mythingtoload.droper)
                {

                    dropStuff tmpDrop = new dropStuff(new Vector2(myDroper.tmpSizeX, myDroper.tmpSizeY), myDroper.tmpStatic, myDroper.tmpTime, myDroper.tmpCoun, this,myDroper.xPlace,myDroper.yPlace,true);
                    dropList.Add(tmpDrop);
                }
                charBody.Position = new Vector2(mythingtoload.playerX, mythingtoload.playerY);
            }



        }


        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.DarkBlue);

            spriteBatch.Begin();
            
            switch (gameState)
            {
                case GameState.shopMenu:
                    {
                        myShop.draw(spriteBatch);
                        break;
                    }
                case GameState.playMenu:
                    {

                        spriteBatch.Draw(menuBackTexture, new Rectangle(0, 0, WIDTH, HEIGHT), Color.White);
                        foreach (gameInMenu levelB in menuList)
                        {
                            if ((playMenuPlace*25 + 25 >= levelB.num) && (playMenuPlace*25<levelB.num))
                            {
                                if (levelB.num > maxLevel)
                                {
                                    spriteBatch.Draw(menuBTexture, levelB.place, Color.White * 0.5f);
                                }
                                if ((levelB.num <= maxLevel) | (building))
                                {
                                    if ((levelB.num >= playMenuPlace * 25) && (playMenuPlace * 25 + 25 >= levelB.num) && (levelB.place.Intersects(new Rectangle(Mouse.GetState().X, Mouse.GetState().Y, 2, 2))))
                                    {
                                        Color tintColor = Color.Cornsilk;
                                        tintColor.A = 30;
                                        spriteBatch.Draw(menuBTexture, levelB.place, tintColor);
                                    }
                                    else { spriteBatch.Draw(menuBTexture, levelB.place, Color.White); }
                                }

                                spriteBatch.DrawString(myFont, levelB.num.ToString(), new Vector2(levelB.place.X + 22, levelB.place.Y + 20), Color.Black, 0.0f, Vector2.Zero, 0.7f, SpriteEffects.None, 0f);
                            }
                        }

                        if (playMenuPlace * 25 + 25 < levelCount)
                        {
                            spriteBatch.Draw(arrowTexture, arrowRight, Color.White);
                        }
                        //spriteBatch.DrawString(myFont, "shop", new Vector2(goShop.X,goShop.Y), Color.Black);
                        if (building == false)
                        {
                            spriteBatch.Draw(storeIconTexture, new Rectangle((int)goShop.X, (int)goShop.Y, 128, 128), newColor);
                        }
                        if (playMenuPlace > 0)
                        {
                            spriteBatch.Draw(arrowTexture, arrowLeft ,null, Color.White,0.0f,new Vector2(0,0),SpriteEffects.FlipHorizontally,0);
                        } //new Rectangle(arrowLeft.X - 16,arrowLeft.Y - 16,arrowLeft.Width,arrowLeft.Height)
                        break;
                    }
                case GameState.builder:
                    {
                        if (info == Info.no) 
                        {
                            Color backColor = new Color(70, 70, 70);
                            GraphicsDevice.Clear(backColor);
                            spriteBatch.Draw(backgroundTexture, new Rectangle(0, 0, WIDTH, HEIGHT), Color.White);
                     
                            gameBuilder.draw(spriteBatch);
                            spriteBatch.DrawString(myFont, "Press And Hold \" i \" for info ", new Vector2(10, 5), Color.White, 0, Vector2.Zero, 0.4f, SpriteEffects.None, 0.5f);
                            if (choose)
                            {
                                foreach (GameShape currentShape in rocks)
                                {
                                    if (currentShape != currSelectedShape) currentShape.draw(spriteBatch);
                                    else currentShape.drawSelected(spriteBatch);
                                }
                            }
                        }
                        else { spriteBatch.Draw(builderTexture, new Rectangle(0, 0, WIDTH, HEIGHT), Color.DarkBlue); }
                        break;
                    }

                case GameState.menu:
                    {
                        
                        
                        //spriteBatch.Draw(charTexture, playGameRect, Color.BurlyWood);
                        //spriteBatch.Draw(charTexture, createGameRect, Color.BurlyWood);
                        spriteBatch.Draw(mainTexture, new Rectangle(0, 0, WIDTH, HEIGHT), Color.White);
                        spriteBatch.DrawString(myFont2, "Mountain Of Rocks", new Vector2(50, 40), Color.Maroon,0.0f,Vector2.Zero,1.7f,SpriteEffects.None,0f);
                        spriteBatch.DrawString(myFont, "Play", new Vector2(playGameRect.X + 10, playGameRect.Y + 5), play);
                        spriteBatch.DrawString(myFont, "Build Level", new Vector2(createGameRect.X + 10, createGameRect.Y + 5), build);
                        spriteBatch.DrawString(myFont, "How To Play", new Vector2(inforec.X + 10, inforec.Y + 5), how);
                        if (isMute)
                            spriteBatch.Draw(muteTexture, muteButton, new Rectangle(0, 0, 128, 128), Color.White);
                        else
                            spriteBatch.Draw(muteTexture, muteButton, new Rectangle(128, 0, 128, 128), Color.White);
                        

                        break;
                    }

                case GameState.play:
                    {
                        Color backColor = new Color(70 , 70, 70);
                        //Color backColor = Color.Brown;
                        GraphicsDevice.Clear(backColor);
                        spriteBatch.Draw(backgroundTexture, new Rectangle(0, 0, WIDTH, HEIGHT), Color.White);
                            
                            // Draw Player
                            // draw player 
                            if (!doBuildWorld)
                            {
                               
                                timeBeforeChange -= gameTime.ElapsedGameTime.TotalSeconds;
                                if (open)
                                {
                                    opentime -= gameTime.ElapsedGameTime.TotalSeconds;
                                }
                                
                                myPlayer.draw(spriteBatch);
                                if ((opentime <= 0) && (j < 3)) { j++; }
                                spriteBatch.Draw(exitTexture,
                                   new Rectangle((int)exitDoor.Position.X, (int)exitDoor.Position.Y, 32, 32), null,
                                   Color.White,0.0f,new Vector2(0,0),SpriteEffects.None,0.8f);


                                foreach (GameShape currentShape in rocks)
                                {
                                    if (currentShape != currSelectedShape) currentShape.draw(spriteBatch);
                                    else currentShape.drawSelected(spriteBatch);
                                }
                                string str = live.ToString();
                                Vector2 FontOrigin = new Vector2(20, 75);
                                spriteBatch.DrawString(myFont, "lives: " + str, new Vector2(50, 80), Color.White, 0, FontOrigin, 0.7f, SpriteEffects.None, 0.5f);
                                spriteBatch.DrawString(myFont, "money: " + playerMoney.ToString(), new Vector2(WIDTH - 180, 80), Color.White, 0, FontOrigin, 0.7f, SpriteEffects.None, 0.5f);
                                
                                // draw particles for effects
                                pManager.DrawParticles(smokeText, shatterTexture);

                                // rocks power
                                if (rocksPower > 0) spriteBatch.DrawString(myFont, "rocks to disappear: " + rocksPower.ToString(), new Vector2(WIDTH - 270, 140), Color.White, 0, FontOrigin, 0.7f, SpriteEffects.None, 0.5f);


                                // Draw the power meter
                                powerController.Draw(spriteBatch);

                                // draw lightning 
                                if (this.lightning != null) this.lightning.Draw(spriteBatch);
                            }
                        
                        break;
                    }
                case GameState.win:
                    {
                        delay -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                        if (delay > 0)
                        {
                            spriteBatch.Draw(levelUpTexture, new Rectangle(0, 0, WIDTH, HEIGHT), Color.White);
                        }
                       // print("good job", gameTime);
                        break;
                    }
                case GameState.lose:
                    {
                        delay -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                        if (delay > 0)
                        {
                            spriteBatch.Draw(gameOverTexture, new Rectangle(0, 0, WIDTH, HEIGHT), Color.White);
                        } 
                        break;
                    }
                case GameState.done:
                    {
                        delay -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                        if (delay > 0)
                        {
                            spriteBatch.Draw(levelDoneTexture, new Rectangle(0, 0, WIDTH, HEIGHT), Color.White);
                        } 
                        break;
                    }
                case GameState.howto:
                    {
                        spriteBatch.Draw(playTexture, new Rectangle(0, 0, WIDTH, HEIGHT), Color.White);
                        break;
                    }
            }

            spriteBatch.End();
            base.Draw(gameTime);
        }


        public void print(string str, GameTime gameTime)
        {
            delay -= (float)gameTime.ElapsedGameTime.TotalSeconds;
            Vector2 FontOrigin = myFont.MeasureString(str) * 2;

            if (delay > 0)
            {             
                spriteBatch.DrawString(myFont, str, new Vector2(WIDTH/2,HEIGHT/2), Color.Black, 0, FontOrigin, 1.0f, SpriteEffects.None, 0.5f);   
            }
            
        }
    }
}
